package com.fx.easyexcel.demo.service;

import ch.qos.logback.core.util.FileUtil;
import com.fx.easyexcel.demo.util.TimeUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Faxon
 * @version 1.0
 * @date 2020-07-04 23:58
 **/
@Service
public class FileService {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileUtil.class);

    /**
     * 压缩文件（夹）为 zip
     *
     * @param sourceFilePath
     * @param fileName
     * @return
     */
    public File toZip(String sourceFilePath, String fileName) {
        File sourceFile = new File(sourceFilePath);
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        File zipFile = null;
        if (!sourceFile.exists()) {
            LOGGER.error("Message：[{}],Time：[{}],Class:[{}]", "待压缩文件夹不存在", TimeUtil.getNowTime(), "FileUtil.Class");
        } else {
            try {
                zipFile = new File(fileName + ".zip");
                if (zipFile.exists()) {
                    LOGGER.info("Message：[{}],Time：[{}],Class:[{}]", "zip文件夹已创建", TimeUtil.getNowTime(), "FileUtil.Class");
                } else {
                    File[] sourceFiles = sourceFile.listFiles();
                    if (null == sourceFiles || sourceFiles.length < 1) {
                        LOGGER.error("Message：[{}],Time：[{}],Class:[{}]", "待压缩文件夹为空", TimeUtil.getNowTime(), "FileUtil.Class");
                    } else {
                        fos = new FileOutputStream(zipFile);
                        zos = new ZipOutputStream(new BufferedOutputStream(fos));
                        byte[] bufs = new byte[1024 * 10];
                        for (File file : sourceFiles) {
                            //创建ZIP实体，并添加进压缩包
                            ZipEntry zipEntry = new ZipEntry(file.getName());
                            zos.putNextEntry(zipEntry);
                            //读取待压缩的文件并写进压缩包里
                            fis = new FileInputStream(file);
                            bis = new BufferedInputStream(fis, 1024 * 10);
                            int read;
                            while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
                                zos.write(bufs, 0, read);
                            }
                        }
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Message：[{}],Time：[{}],Class:[{}]", "压缩失败", TimeUtil.getNowTime(), "FileUtil.Class");
                e.printStackTrace();
                return null;
            } finally {
                //关闭流
                try {
                    if (null != bis) {
                        bis.close();
                    }
                    if (null != fis) {
                        fis.close();
                    }
                    if (null != zos) {
                        zos.close();
                    }
                    if (null != fos) {
                        fos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return zipFile;
    }

    /**
     * 将 multipartFile 转为File对象
     *
     * @param multipartFile
     * @return File
     * @throws IOException
     */
    public File toFile(MultipartFile multipartFile) throws IOException {
        File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
        InputStream inputStream = multipartFile.getInputStream();
        OutputStream os = new FileOutputStream(file);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        inputStream.close();
        return file;
    }

    /**
     * response返回文件
     *
     * @param response
     * @param fileName
     * @param inputData
     * @throws IOException
     */
    public void downloadFile(HttpServletResponse response, String fileName, InputStream inputData) throws IOException {
        //放到缓冲流里面
        BufferedInputStream bins = new BufferedInputStream(inputData);
        //获取文件输出IO流
        OutputStream outs = response.getOutputStream();
        BufferedOutputStream bouts = new BufferedOutputStream(outs);
        response.setContentType("application/x-download");
        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        //开始向网络传输文件流
        while ((bytesRead = bins.read(buffer, 0, 8192)) != -1) {
            bouts.write(buffer, 0, bytesRead);
        }
        bouts.flush();//这里一定要调用flush()方法
        inputData.close();
        bins.close();
        outs.close();
        bouts.close();
    }

    /**
     * 获取文件名
     *
     * @param file
     * @return
     */
    public String getFileName(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)) {
            return TimeUtil.getNow("MM月dd日") + "的准考证";
        }
        return originalFilename.substring(0, originalFilename.lastIndexOf("."));
    }

    /**
     * 迭代删除文件(夹)
     *
     * @param file 文件夹
     */
    @Async
    public void deleteDir(File file) {
        boolean flag;
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if(files!=null && files.length!=0){
                for (File f : files) {
                    deleteDir(f);
                }
            }
        }
        flag = file.delete();
        while (!flag){
            System.gc();
            flag = file.delete();
        }
    }

}
